package cn.cnlee.arch.event;


import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;

import java.util.concurrent.ConcurrentHashMap;

import cn.cnlee.arch.util.Logger;


/**
 * 事件总线 类似EventBus
 * <p>
 * <p>
 * LiveBus.get().postEvent("LiveData","hi LiveData");
 * <p>
 * <p>
 * LiveBus.get().getChannel("LiveData").observe(this, new Observer<Object>() {
 *
 * @Override public void onChanged(@Nullable Object o) {
 * Log.e("onChanged",((String)o));
 * }
 * });
 */
public class LiveBus {

    private static volatile LiveBus instance;

    private final ConcurrentHashMap<Object, LiveBusData<Object>> mLiveBusDataCache;

    private LiveBus() {
        mLiveBusDataCache = new ConcurrentHashMap<>();
    }

    public static LiveBus get() {
        if (instance == null) {
            synchronized (LiveBus.class) {
                if (instance == null) {
                    instance = new LiveBus();
                }
            }
        }
        return instance;
    }


    public <T> MutableLiveData<T> getChannel(Object eventKey) {
        return getChannel(eventKey, "");
    }

    public <T> MutableLiveData<T> getChannel(Object eventKey, String tag) {
        return (MutableLiveData<T>) getChannel(eventKey, tag, Object.class);
    }

    public <T> MutableLiveData<T> getChannel(Object eventKey, Class<T> tClass) {
        return getChannel(eventKey, null, tClass);
    }

    public <T> MutableLiveData<T> getChannel(Object eventKey, String tag, Class<T> tClass) {
        String channelKey = makeChannelKey(eventKey, tag);
        LiveBusData liveBusData;
        if (!mLiveBusDataCache.containsKey(channelKey)) {
            liveBusData =  new LiveBusData<>(true);
            mLiveBusDataCache.put(channelKey,liveBusData);
//            Logger.e(channelKey + "======getChannel==不存在=== " + liveBusData);
        } else {
            liveBusData = mLiveBusDataCache.get(channelKey);
//            liveBusData.isFirstSubscribe = false;
//            Logger.e(channelKey + "======getChannel==已缓存=== " + liveBusData);
        }
        return liveBusData;
    }

    public <T> MutableLiveData<T> postEvent(Object eventKey, T value) {
        return postEvent(eventKey, null, value);
    }

    public <T> MutableLiveData<T> postEvent(Object eventKey, String tag, T value) {
        String channelKey = makeChannelKey(eventKey, tag);
        MutableLiveData<T> mutableLiveData = getChannel(channelKey);
        Logger.e(channelKey + "======postEvent===== " + value);
        mutableLiveData.postValue(value);
        return mutableLiveData;
    }

    private String makeChannelKey(Object eventKey, String tag) {
        String mEventKey;
        if (!TextUtils.isEmpty(tag)) {
            mEventKey = eventKey + tag;
        } else {
            mEventKey = (String) eventKey;
        }
        return mEventKey;
    }

    public static class LiveBusData<T> extends MutableLiveData<T> {

        private boolean isFirstSubscribe;

        LiveBusData(boolean isFirstSubscribe) {
            this.isFirstSubscribe = isFirstSubscribe;
        }

        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
            super.observe(owner, new ObserverWrapper<>(observer, isFirstSubscribe));
        }
    }

    private static class ObserverWrapper<T> implements Observer<T> {

        private Observer<T> observer;

        private boolean isChanged;

        private ObserverWrapper(Observer<T> observer, boolean isFirstSubscribe) {
            this.observer = observer;
            isChanged = isFirstSubscribe;
        }

        @Override
        public void onChanged(@Nullable T t) {
            if (isChanged) {
                if (observer != null) {
                    observer.onChanged(t);
                }
            } else {
                isChanged = true;
            }
        }

    }

    public void clear(Object eventKey) {
        clear(eventKey, null);
    }

    public void clear(Object eventKey, String tag) {
        if (mLiveBusDataCache.size() > 0) {
            String mEventKey = makeChannelKey(eventKey, tag);
            mLiveBusDataCache.remove(mEventKey);
        }
    }

}
